import { BaseEvent } from "./base";
import { INPUT_TYPE } from "./const";
import { BaseOpt, InsertOpt, ReplaceOpt, DeleteOpt } from '../operations'
import { SelectionModel } from "../models";

class InputEventer extends BaseEvent {

  private isComposEditing = false

  addEventListen(): void {
    this.element.addEventListener('beforeinput', this._onBeforeInput.bind(this))
    this.element.addEventListener('compositionstart', this._onBeforeComposInput.bind(this))
    this.element.addEventListener('compositionend', this._onAfterComposInput.bind(this))
  }
  removeEventListen(): void {

  }
  _onBeforeInput(e: InputEvent) {
    e.preventDefault()
    if (e.inputType === INPUT_TYPE.INSERT) {
      if (e.data) {
        this.editor.require(this._onContentInsert(e.data))
      }
    } else if (e.inputType === INPUT_TYPE.DELETE) {
      this.editor.require(this._onContentDel())
    } else if (e.inputType === INPUT_TYPE.INSERT_PARAGRAPH) {
      this.editor.require(this._onContentInsert('\n'))
    } else if (e.inputType === INPUT_TYPE.INSERT_PASTE) {
      let text = e.dataTransfer?.getData("text/plain")
      if(text){
        this.editor.require(this._onContentInsert(text))
      }
    }
  }
  _onBeforeComposInput(e: CompositionEvent) {
    this.isComposEditing = true
    this.editor.storeSelection()
  }
  _onAfterComposInput(e: CompositionEvent) {
    e.preventDefault()
    if (this.isComposEditing) {
      this.editor.restoreSelection()
      this.isComposEditing = false
    }
    if (e.data) {
      this.editor.require(this._onContentInsert(e.data))
    }
  }

  _onContentInsert(body: string) {
    return (selection: SelectionModel) => {
      let opt: BaseOpt
      if (selection.length > 0) {
        opt = new ReplaceOpt(selection.index, selection.length, body)

      } else {
        opt = new InsertOpt(selection.index, body)
      }
      this.editor.commit(opt)
    }
  }
  _onContentDel() {
    return (selection: SelectionModel) => {
      let start, length
      if (selection.length) {
        start = selection.index
        length = selection.length
      } else {
        start = selection.index - 1
        length = 1
      }
      let opt = new DeleteOpt(start, length)
      this.editor.commit(opt)
    }
  }
}

export default InputEventer